﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;

namespace SIAD.Model
{
    /// <summary>
    /// Représente le déroulement d'un jeu de plateau
    /// </summary>
    abstract class Game
    {
        #region Properties
        /// <summary>
        /// le nombre de joueur
        /// </summary>
        protected List<Player> PlayerList;

        /// <summary>
        /// Permet de s'assurer que tout se fera dans un autre thread que le
        /// thread graphique
        /// </summary>
        BackgroundWorker gameWorker;

        #endregion

        #region Abstract Method
        /// <summary>
        /// Initialisation du jeu
        /// </summary>
        public abstract void initializeGame();

        /// <summary>
        /// Jeu d'un joueur
        /// </summary>
        /// <param name="player">Le joueur en question</param>
        public abstract void makePlay(Player player);

        /// <summary>
        /// Vérifie si la partie n'est pas finie
        /// </summary>
        /// <returns>true si la partie est finie, false sinon</returns>
        public abstract bool endOfGame();

        /// <summary>
        /// Affiche le winner()
        /// </summary>
        public abstract void printWinner();

        #endregion

        /// <summary>
        /// Template Méthod permettant de spécifier le comportement du jeu
        /// </summary>
        public void playOneGame()
        {
            gameWorker = new BackgroundWorker();

            gameWorker.WorkerReportsProgress = false;
            gameWorker.WorkerSupportsCancellation = true;

            gameWorker.DoWork += new DoWorkEventHandler(DoWork);
            gameWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(RunWorkerCompleted);

            gameWorker.RunWorkerAsync();                
        }

        /// <summary>
        /// Permet d'arrêter le jeu
        /// </summary>
        public void stopGame()
        {
            gameWorker.CancelAsync();
        }
        #region Constructor
        /// <summary>
        /// Constructeur qui permet d'instancier le backgrounworker
        /// </summary>
        public Game()
        {
            PlayerList = new List<Player>();            
        }
        #endregion

        #region BackgroundWorker Handler
        /// <summary>
        /// Permet de lancer le travail en arrière plan
        /// </summary>
        private void DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;

            this.Process(worker, e);
        }

        /// <summary>
        /// Permet de spécifier que le travail a été réaliser !!
        /// </summary>
        private void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            // Pour l'instant on ne fais rien mais pourquoi pas gérer un affichage ici
        }
        #endregion

        #region Private Method
        /// <summary>
        /// Lance le jeu
        /// </summary>
        private void Process(BackgroundWorker worker, DoWorkEventArgs e)
        {
            initializeGame();

            //******************************
            //on test si rien n'a été annulé
            if (worker.CancellationPending)
            {
                e.Cancel = true;
                return;
            }
            //******************************

            int j = 0;
            while (!endOfGame())
            {
                makePlay(PlayerList[j]);
                j = (j + 1) % PlayerList.Count;
                //******************************
                //on test si rien n'a été annulé
                if (worker.CancellationPending)
                {
                    e.Cancel = true;
                    return;
                }
                //******************************
            }
            printWinner();
        }
        #endregion
    }
}
